using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BoldBrick.Core.Logging;
using BoldBrick.OneIntranet.HR.DataObjects.ContentTypes;
using BoldBrick.OneIntranet.HR.DataObjects.ContentTypes.CandidatesContentTypes;
using BoldBrick.OneIntranet.HR.DataObjects.Lists;
using BoldBrick.OneIntranet.HR.DataObjects.Lists.CandidatesListData;
using BoldBrick.SharePoint.CommonControls.Logging;
using Microsoft.SharePoint;
using BoldBrick.SharePoint.CommonControls.Extensions;

namespace BoldBrick.OneIntranet.HR.Features.ContentTypeReset
{
	/// <summary>
	/// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
	/// </summary>
	/// <remarks>
	/// The GUID attached to this class may be used during packaging and should not be modified.
	/// </remarks>

	[Guid("312637fe-3354-44ba-a215-dcb1f3bea4bd")]
	public class ContentTypeResetEventReceiver : SPFeatureReceiver
	{
		public override void FeatureActivated(SPFeatureReceiverProperties properties)
		{	
			using (SPWeb webParent = properties.Feature.Parent as SPWeb)
			{
				if (webParent == null)
				{
					FeatureLogger.Write<ContentTypeResetEventReceiver>(LogLevel.Error, "Web not found in '{0}' feature.", properties.Feature.DefinitionId);
					return;
				}

				Guid webID = webParent.ID;
				Guid siteID = webParent.Site.ID;

				// add site content types
				PerformWebAction(siteID, webID, web =>
				{
					EnsureSiteContentTypes(webParent, Lists.CandidatesList, ContentTypes.ResultContentType);

					EnsureSiteContentTypes(webParent, Lists.WorkflowsList, ContentTypes.WorkflowStepContentType);
					
					EnsureSiteContentTypes(webParent, Lists.TasksList, ContentTypes.HRTaskContentType);
				});
				
				// set order of content types in folders
				PerformWebAction(siteID, webID, web =>
				{
					ResetContentTypesUniqueOrder(webParent, Lists.CandidatesList, ContentTypes.CandidateContentType);

					ResetContentTypesUniqueOrder(webParent, Lists.WorkflowsList, ContentTypes.WorkflowContentType);
				});
			}
		}

		/// <summary>
		/// Adds child site content types of 
		/// </summary>
		/// <param name="web">Parent web of the list</param>
		/// <param name="list">List data object</param>
		/// <param name="parentContentType">Parent content type data object</param>
		private static void EnsureSiteContentTypes(SPWeb web, SharePoint.CommonControls.DataObjects.Base.BaseList list, BaseContentType parentContentType)
		{
			uint language = web.Language;

			FeatureLogger.Write<ContentTypeResetEventReceiver>(LogLevel.Info, "Add site content types to '{0}' list.", list.GetListTitle(language));

			SPList spList = web.GetList(list);
			if (spList == null)
			{
				FeatureLogger.Write<ContentTypeResetEventReceiver>(LogLevel.Info, "'{0}' list not found.", list.GetListTitle(language));
				return;
			}

			foreach (SPContentType contentTypeSite in web.ContentTypes)
			{
				if (contentTypeSite.Id.IsChildOf(parentContentType.ID) && contentTypeSite.Id != parentContentType.ID)
				{
					SPContentType contentTypeList = spList.ContentTypes.GetChildContentType(contentTypeSite.Id);
					if (contentTypeList == null)
					{
						spList.ContentTypes.Add(contentTypeSite);
					}
				}
			}
		}

		/// <summary>
		/// Resets content type unique order on each folder of the list
		/// </summary>
		/// <param name="web">Parent web of the list</param>
		/// <param name="list">List data object</param>
		/// <param name="rootFolderContentType">Root folder content type data object</param>
		private static void ResetContentTypesUniqueOrder(SPWeb web, BaseList list, BaseContentType rootFolderContentType)
		{
			uint language = web.Language;

			FeatureLogger.Write<ContentTypeResetEventReceiver>(LogLevel.Info, "Setup '{0}' list.", list.GetListTitle(language));

			IContentTypeUniqueOrderService service = list as IContentTypeUniqueOrderService;

			if (service == null)
			{
				FeatureLogger.Write<ContentTypeResetEventReceiver>(LogLevel.Info, "'{0}' list does not implement IContentTypeUniqueOrderService.", list.GetListTitle(language));
				return;
			}

			SPList spList = web.GetList(list);
			if (spList == null)
			{
				FeatureLogger.Write<ContentTypeResetEventReceiver>(LogLevel.Info, "'{0}' list not found.", list.GetListTitle(language));
				return;
			}

			// setup root folder
			SPContentType spRootFolderContentType = spList.ContentTypes.GetChildContentType(rootFolderContentType.ID);
			SPFolder rootFolder = spList.RootFolder;
			rootFolder.UniqueContentTypeOrder = new List<SPContentType>
			                                           	{
			                                           		spRootFolderContentType
			                                           	};
			rootFolder.Update();

			// setup folders)
			foreach (SPFolder folder in rootFolder.SubFolders)
			{
				service.SetupContentTypeUniqueOrder(spList, folder);
			}
		}

		/// <summary>
		/// Perform action on a new instance of the <see cref="SPWeb"/> object
		/// </summary>
		/// <param name="siteID">Site ID of the web</param>
		/// <param name="webID">Web ID of the web</param>
		/// <param name="webAction">Action to perform</param>
		private static void PerformWebAction(Guid siteID, Guid webID, WebAction webAction)
		{
			using (SPSite site = new SPSite(siteID))
			{
				using (SPWeb web = site.OpenWeb(webID))
				{
					webAction(web);
				}
			}
		}

		private delegate void WebAction(SPWeb web);
	}
}
